<template>
  <div class="root_app">
    <ant-v ref="graphDom"/>
  </div>
</template>
<script setup>
import AntV from '@/components/graph/index.vue'
import {onMounted, ref} from "vue";
import graphData from '@/assets/data3'
import graphData1 from '@/assets/data4'
import graphData2 from '@/assets/data5'
import emitter from "@/utils/emitter.js";

let graphDom = ref()
let currentConfigGraphData = ref({})

// 初始化图谱
async function readyGraph(configGraphData) {
  if (configGraphData.data.nodes.length >= 60) {
    configGraphData.optionsConfig.defaultAutoFit = 'view'
  }
  graphDom.value.initGraph(configGraphData);
}

onMounted(() => {
  let startNode = graphData2.nodes[0]
  let graphData = calcGraph(graphData2, startNode)
  // 接收消息
  receiveMessage()
  const data = {
    data: graphData,
    optionsConfig: {
      isNewData: true,
      bindNodeClick: true,
      layout: "d3Force",
      padding: [80, 80, 80, 80],
      animation: false,
      defaultNodeSize: 40,
      defaultLabelSize: 14,
      defaultNodeFill: null,
      defaultAutoFit: 'center',
    },
    configuration: {
      edgeLabel: null,
      edgeId: null,
      nodeId: "id",
      nodeLabel: "label",
      source: "source",
      target: "target",
      nodeType: 'nodeType'
    }
  }
  readyGraph(data)
  return
  //向父元素发送消息
  setTimeout(() => {
    const params = {
      data: {
        status: 200,
        msg: "iframe已经加载完成"
      },
      signal: 'iframeFinish'
    }
    // 向父页面发送消息
    window.parent.postMessage(params, '*');
  })
})


// 接收消息
function receiveMessage() {
  //接收父组件的消息
  window.addEventListener('message', function (event) {
    // 处理接收到的消息
    if (event.data.signal && event.data.signal === 'graphData') {
      // 医学院数据
      if (event.data.data === 1) {
        const data = {
          data: graphData1,
          optionsConfig: {
            isNewData: true,
            bindNodeClick: true,
            layout: "d3Force",
            padding: [80, 80, 80, 80],
            animation: false,
            defaultNodeSize: 40,
            defaultLabelSize: 14,
            defaultNodeFill: null,
            defaultAutoFit: 'center',
          },
          configuration: {
            edgeLabel: null,
            edgeId: null,
            nodeId: "id",
            nodeLabel: "name",
            source: "Source",
            target: "Target",
            nodeType: 'type'
          }
        }
        currentConfigGraphData = data
        readyGraph(data)
      } else {
        // 地理数据
        const data = {
          data: graphData,
          optionsConfig: {
            isNewData: true,
            bindNodeClick: true,
            layout: "d3Force",
            padding: [80, 80, 80, 80],
            animation: false,
            defaultNodeSize: 40,
            defaultLabelSize: 14,
            defaultNodeFill: null,
            defaultAutoFit: 'center',
          },
          configuration: {
            edgeLabel: null,
            edgeId: null,
            nodeId: "id",
            nodeLabel: "label",
            source: "source",
            target: "target",
            nodeType: 'nodeType'
          }
        }
        currentConfigGraphData = data
        // 初始化图谱
        getData(data, 2)
      }
    }
  });
  emitter.on('refreshData', (params) => {
    if (params.data.id === '2') {
      let graphData = calcGraph(graphData2, params.data)
      const data = {
        data: graphData,
        optionsConfig: {
          isNewData: true,
          bindNodeClick: true,
          layout: "d3Force",
          padding: [80, 80, 80, 80],
          animation: false,
          defaultNodeSize: 40,
          defaultLabelSize: 14,
          defaultNodeFill: null,
          defaultAutoFit: 'center',
        },
        configuration: {
          edgeLabel: null,
          edgeId: null,
          nodeId: "id",
          nodeLabel: "label",
          source: "source",
          target: "target",
          nodeType: 'nodeType'
        }
      }
      // return
      readyGraph(data)
    }
    if (params.data.id === '7') {
      let graphData = calcGraph1(graphData2, params.data)
      const data = {
        data: graphData,
        optionsConfig: {
          isNewData: true,
          bindNodeClick: true,
          layout: "d3Force",
          padding: [80, 80, 80, 80],
          animation: false,
          defaultNodeSize: 40,
          defaultLabelSize: 14,
          defaultNodeFill: null,
          defaultAutoFit: 'center',
        },
        configuration: {
          edgeLabel: null,
          edgeId: null,
          nodeId: "id",
          nodeLabel: "label",
          source: "source",
          target: "target",
          nodeType: 'nodeType'
        }
      }
      // return
      readyGraph(data)
    }
  })
}

let aNodes = [], //当前点击节点
    aEdges = [], // 串联边
    butNodes = [], //移除节点
    prevEdges = [];// 上一层级的边
// 新的图谱数据
let newGraphData = {
  nodes: [],
  edges: []
}

// 计算图谱
function calcGraph(data, startNode) {
  // 把当前点击的节点放进盒子里面
  aNodes.push(startNode)
  // 清空原有的节点和边
  newGraphData.nodes = []
  newGraphData.edges = []
  // 获取串联边
  linkEdge(data)
  //移除不需要的节点
  removeNodes(data, startNode)
  // 获取点击节点的向下的边
  let floorEdges = data.edges.filter(v => v.source === startNode.id)
  prevEdges = floorEdges
  // 获取下一层级的节点
  getNextFloorNodes(data, floorEdges)
  // 返回新的图谱数据
  return newGraphData
}

// 串连边
function linkEdge(data) {
  aEdges = []
  aNodes.forEach((item, index, arr) => {
    let edge = data.edges.find((v) => {
      return v.source === item.id && v.target === arr[index + 1]?.id
    })
    if (edge) {
      aEdges.push(edge)
    }
  })
}

// 移除不需要的节点
function removeNodes(data, startNode) {
  prevEdges.forEach(v => {
    let filterNodes = data.nodes.filter(item => {
      return v.target === item.id && item.id !== startNode.id
    })
    if (filterNodes?.length) {
      butNodes.push(...filterNodes)
    }
  })
}

//获取下一层级的节点
function getNextFloorNodes(data, floorEdges) {
  floorEdges.forEach(v => {
    const nodes = data.nodes.find(item => v.target === item.id)
    if (nodes) {
      newGraphData.nodes.push(nodes)
    }
  })
  newGraphData.nodes.push(...aNodes)
  newGraphData.edges = [...floorEdges, ...aEdges]
}

// 计算最后一级图谱
function calcGraph1(data, startNode) {
  newGraphData.nodes = []
  let idsList = butNodes.map(v => v.id.toString())
  idsList = [...idsList, "8", "9", "10", "11"]
  data.nodes.forEach(item => {
    if (!idsList.includes(item.id)) {
      newGraphData.nodes.push(item)
    }
  })
  newGraphData.edges = data.edges.filter(v => {
    return !idsList.includes(v.source) && !idsList.includes(v.target)
  })
  return newGraphData
}
</script>
<style scoped>
.root_app {
  width: 100%;
  height: 100%;
  padding: 20px;
  background: rgba(255, 255, 255, 1);
  backdrop-filter: blur(10px);
  box-sizing: border-box;
  position: relative;
}
</style>
